/* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/


/*************************************************************************
 * File: python_object.cpp
 *************************************************************************
 *\author: starlove
 *************************************************************************/

#include <script/python/python.h>
#include <network/service.h>

PYCLASS_INIT(CPyClassBase, "ClassBase");

PYCLASS_INIT(CPyServer, "Server");

PYCLASS_BEGIN_METHOD_DEF(CPyServer)
PYCLASS_ADD_METHOD("SetCallback", CPyServer::SetCallback)
PYCLASS_ADD_METHOD("Send", CPyServer::Send)
PYCLASS_ADD_METHOD("Response", CPyServer::HttpProcess)
PYCLASS_END_METHOD_DEF(CPyServer)

PYCLASS_IMP_INTERFACE(CPyServer)

PyObject* CPyServer::SetCallback(CPyServer *self, PyObject* args)
{
    if( !args )
        Py_RETURN_FALSE;
    if(!self->pMachine)
        Py_RETURN_FALSE;
    int         tp;
    PyObject    *pType,*pObjFunc;
    if( !PyArg_UnpackTuple(args,"ref",2,2,&pType,&pObjFunc) )
        Py_RETURN_FALSE;
    tp = PyInt_AS_LONG(pType);
    if(tp == eCBTP_HTTP)
    {
    	self->SetHttpFunc(pObjFunc);
    	PyObject *pfn = PyObject_GetAttrString((PyObject *)self, "Response");
		self->pMachine->SetCallback(tp, pfn);
    }else
		self->pMachine->SetCallback(tp, pObjFunc);
    Py_RETURN_TRUE;
}

PyObject *CPyServer::HttpProcess(CPyServer *self, PyObject* args)
{
    //PyObject *pySck ,*pyStatusCode, *pyResponseHeader, *pyData;
    //if( !PyArg_UnpackTuple(args,"ref", 4, 4, &pySck, &pyStatusCode, &pyResponseHeader, &pyData) )
    //    Py_RETURN_NONE;

	PyObject *pySck, *pyRequest, *pyResponse;
    if( !PyArg_UnpackTuple(args,"ref", 2, 2, &pySck, &pyRequest) )
        Py_RETURN_NONE;

	if(!pySck)
        Py_RETURN_NONE;

    int nPeerId = PyInt_AS_LONG(pySck);

    pyResponse = PyDict_New();
    Py_XINCREF(pyResponse);
    PyObject *pyRet = PyObject_CallFunction(self->GetHttpFunc(), "OO", pyRequest, pyResponse);

    char *szData = NULL;
    char *szStatus = NULL;
	PyObject *pyStatus = NULL;
	PyObject *pyData = NULL;
    if( pyRet && PyTuple_Check(pyRet) )
    {
    	PyObject *pyStatus = PyTuple_GetItem(pyRet, 0);
    	PyObject *pyData = PyTuple_GetItem(pyRet, 1);
        szStatus = PyString_AsString(pyStatus);
        szData = PyString_AsString(pyData);
    }

    self->pMachine->SendHttpRetToPeer(nPeerId, pyResponse, szStatus, szData);

	PyEx_XDECREF(pyStatus);
	PyEx_XDECREF(pyData);
	PyEx_XDECREF(pyResponse);
    Py_RETURN_NONE;
}

PyObject* CPyServer::Send(CPyServer *self, PyObject* args)
{
    if( !args )
        Py_RETURN_FALSE;
    if(!self->pMachine)
        Py_RETURN_FALSE;
    PyObject    *pyPeerId,*pObjFunc;
    if( !PyArg_UnpackTuple(args,"ref",2,2,&pyPeerId,&pObjFunc) )
        Py_RETURN_FALSE;
    int nPeerId = PyInt_AS_LONG(pyPeerId);
    self->pMachine->SendToPeer(nPeerId, pObjFunc);
    Py_RETURN_TRUE;
}

PYCLASS_INIT(CPyClient, "Client");

PYCLASS_BEGIN_METHOD_DEF(CPyClient)
PYCLASS_ADD_METHOD("SetCallback", CPyClient::SetCallback)
PYCLASS_ADD_METHOD("Connect", CPyClient::Connect)
PYCLASS_ADD_METHOD("Send", CPyClient::Send)
PYCLASS_ADD_METHOD("Close", CPyClient::Close)
PYCLASS_ADD_METHOD("Lookup", CPyClient::Lookup)
PYCLASS_END_METHOD_DEF(CPyClient)

PYCLASS_IMP_INTERFACE(CPyClient)

PyObject *CPyClient::SetCallback(CPyClient *self, PyObject* args)
{
    if( !args )
        Py_RETURN_FALSE;
    if(!self->pMachine)
        Py_RETURN_FALSE;
    int         tp;
    PyObject    *pType,*pObjFunc;
    if( !PyArg_UnpackTuple(args,"ref",2,2,&pType,&pObjFunc) )
        Py_RETURN_FALSE;
    tp = PyInt_AS_LONG(pType);
    if(tp == eCBTP_HTTP)
        Py_RETURN_FALSE;
    self->pMachine->SetCallback(tp, pObjFunc);
    Py_RETURN_TRUE;
}

PyObject *CPyClient::Connect(CPyClient *self, PyObject* args)
{
    if( !args )
        Py_RETURN_FALSE;

    PyObject *pyAddr;
    PyObject *pyPort;
    unsigned int uPort = 0;
    if( !PyArg_UnpackTuple(args, "ref", 2, 2, &pyAddr, &pyPort) )
        Py_RETURN_FALSE;

    char *szAddr = PyString_AsString(pyAddr);
    uPort = PyInt_AsLong(pyPort);

    if( !self->GetPeer()->Connect((const char *)szAddr, uPort) )
        Py_RETURN_FALSE;

    CMLSENetwork::SetSocketOpt((SOCKET)self->GetPeer()->GetIOHandle());
    Py_RETURN_TRUE;
}

PyObject *CPyClient::Send(CPyClient *self, PyObject* args)
{
    if( !args )
        Py_RETURN_FALSE;
    if(!self->pMachine)
        Py_RETURN_FALSE;
    PyObject *pyObjData;
    if( !PyArg_UnpackTuple(args,"ref",1,1,&pyObjData) )
        Py_RETURN_FALSE;

    NETWORKBUFFER buf;
    self->pMachine->PreSendData(&buf, pyObjData);
    self->GetPeer()->SendData(buf.GetPtr(), buf.GetDataSize());

    Py_RETURN_TRUE;
}

PyObject *CPyClient::Close(CPyClient *self)
{
    if(!self->pMachine)
        Py_RETURN_FALSE;
    self->GetPeer()->Destory();
    Py_RETURN_TRUE;
}

PyObject *CPyClient::Lookup(CPyClient *self, PyObject* args)
{
    self->GetPeer()->RecvData();
    Py_RETURN_TRUE;
}

PyObject* CreateTimer(PyObject *self, PyObject* args)
{
    if( !args )
        Py_RETURN_FALSE;
    unsigned long internal = 1;
    char flag = 0;
    PyObject *pObjInterval, *pObjFlag;
    PyObject *pObjFunc, *pObjParam;
    if( !PyArg_UnpackTuple(args,"ref",4,4,&pObjInterval, &pObjFunc, &pObjFlag, &pObjParam) )
        Py_RETURN_NONE;

    internal = PyInt_AsLong(pObjInterval);
    flag = static_cast<char>(PyInt_AsLong(pObjFlag));

    CPyTimer *pT = new CPyTimer();
    pT->SetOnTimer(internal, flag, pObjFunc, pObjParam);
    ITimer::AddTimer(dynamic_cast<ITimer *>(pT));
    return Py_BuildValue("i", pT->GetPtr()->id);
}

PyObject* DestoryTimer(PyObject *self, PyObject* args)
{
    int id = 0;
    if( !PyArg_ParseTuple(args, "i:ref", &id) )
        Py_RETURN_FALSE;
    ITimer::DelTimer(id);
    Py_RETURN_TRUE;
}

PyObject* GetMachineVersion(PyObject *self)
{
    return Py_BuildValue("s", __MLSE_PYTHON_SCRIPTMACHINE_VERSION__);
}
